<style>
.chart_dom {
  width: 99%;
  min-width: 99%;
  max-width: 99%;
  background-color: white;
}
.echarts-box {

}
</style>
<template>
  <div class="echarts-box">
    <div ref="senseChartDomRef" class="chart_dom" :style="{ height: chartDomHeight + 'px'}"></div>
    <div ref="signalChartDomRef" class="chart_dom" :style="{ height: chartDomHeight + 'px'}"></div>
  </div>
</template>

<script setup lang="ts">
import * as echarts from "echarts";
import {onMounted, onUnmounted, onUpdated, ref} from "vue";

import config from "../assets/config.json"
import walden from "../assets/chart_themes/walden.json"
import axios from "axios";
import * as DataResponse from "../class/DataResponse"
import DeviceDataChartOption from "../class/DeviceDataChartOption";

interface Source {
  [key: string]: any;
}

let props = defineProps({
  deviceNumber: String,
  dataTag1: String,
  dataTag2: String,
  updateTimeout: {
    type: Number,
    default: 1000*60*3
  },
  chartView: String
});
const deviceNumber = props.deviceNumber == undefined ? "" : props.deviceNumber;
const dataTag1 = props.dataTag1 == undefined ? "数据1" : props.dataTag1;
const dataTag2 = props.dataTag2 == undefined ? "数据2" : props.dataTag2;
const updateDelay = props.updateTimeout;
let timer: any;

const chartView = props.chartView == undefined ? "line" : props.chartView;
const maxDataCount = 20;

const senseChartDomRef = ref<HTMLElement>();
const signalChartDomRef = ref<HTMLElement>();

let lineChart_1_option = new DeviceDataChartOption();
let lineChart_2_option = new DeviceDataChartOption();

let chart1: echarts.EChartsType;
let chart2: echarts.EChartsType;
lineChart_1_option.color = ["#3fb1e3"];
lineChart_2_option.color = ["#6be6c1"];

let resizeInterval = -1;
let chartDomHeight = ref(document.documentElement.clientHeight * 0.4);

onMounted(() => {
  initChart(<HTMLElement>senseChartDomRef.value, lineChart_1_option, dataTag1, true, [0, 100]).then(chart => {
    chart1 = chart;
    setChartView(chart1, lineChart_1_option, chartView);
  });
  initChart(<HTMLElement>signalChartDomRef.value, lineChart_2_option, dataTag2, false, [0, 120]).then(chart => {
    chart2 = chart;
    setChartView(chart2, lineChart_2_option, chartView);
    resizeChart();
  });

  timer = _setInterval(() => {
    updateChart(chart1 as echarts.EChartsType, lineChart_1_option, props.dataTag1 as string);
    updateChart(chart2 as echarts.EChartsType, lineChart_2_option, props.dataTag2 as string);
    console.log("updated");
  }, updateDelay);

  window.onresize = () => {
    chartDomHeight.value = document.documentElement.clientHeight * 0.4;
    resizeChart();
  };
});

const _setInterval = (fn: any, delay: number, ...rest: any) => {
  let lastTime = Date.now();
  return setInterval(() => {
    let now = Date.now();
    if (now - lastTime >= delay) {
      lastTime = lastTime + delay;
      fn(...rest);
    }
  }, 100);
};

function resizeChart() {
  chart1?.resize();
  chart2?.resize();
  resizeInterval = setInterval(() => {
    chart1?.resize();
    chart2?.resize();
  }, 10);
  setTimeout(() => {clearInterval(resizeInterval);}, 3000);
}

onUnmounted(() => {
  // chart1?.dispose();
  // chart2?.dispose();
  clearInterval(timer);
});

function getData(deviceNumber: string, init: boolean=false) : Promise<DataResponse.Datapack[]> {
  let dataCount = 1;
  if (init) {
    dataCount = maxDataCount;
  }
  return new Promise<DataResponse.Datapack[]>((resolve, reject) => {
    axios({
      baseURL: `http://${config.host}:${config.port}`,
      url: `${config.apiPrefix}/${deviceNumber}/${config.apiSuffix.getData}`,
      method: "GET",
      params: {
        count: dataCount
      }
    }).then(response => {
      if (response.status == 200 && response.data.status == "success") {
        resolve(response.data.datapacks);
      } else {
        throw Error("status is not success.");
      }
    }).catch(function (error) {
      reject(error);
    });
  });
}


function setChartView(chart: echarts.EChartsType, chartOption: DeviceDataChartOption, chartView: string) {
  if (chartView == 'bar') {
    // 变换为柱状图
    // x轴类型设置为分类
    chartOption.xAxis.type = "category";
    // 图表设置为柱状图显示
    chartOption.series[0].type = "bar";
    chartOption.series[0].datasetIndex = 1;
    chartOption.xAxis.axisLabel = { interval: 0, rotate: 30 }
  } else if (chartView == 'line') {
    // 变换为折线图
    // x轴类型设置为时间
    chartOption.xAxis.type = "time";
    // 图表设置为折线图显示
    chartOption.series[0].type = "line";
    chartOption.series[0].datasetIndex = 0;
    chartOption.xAxis.axisLabel = { interval: 0, rotate: 0 }
  }
  // 为图表设置选项使其生效
  chart.setOption(chartOption as echarts.EChartsOption);
}


async function updateChart(chart: echarts.EChartsType, chartOption: DeviceDataChartOption, dimensionTag: string) {
  // 获取最新的数据
  let datapack = (await getData(deviceNumber, false).catch((err) => {console.log(err)}) as DataResponse.Datapack[])[0];
  // 在数据包中查找特定维度的数据
  if (datapack.data.length > 0) {
    let dimensionIndex = 0;
    for (let i = 0; i < datapack.data.length; i++) {
      if (datapack.data[i].name == dimensionTag) {
        dimensionIndex = i;
        break;
      }
    }
    // 为图表选项新增数据
    let source: Source = {};
    source['时间'] = new Date(datapack.data[dimensionIndex].time).toLocaleString();
    source[dimensionTag] = datapack.data[dimensionIndex].value;
    chartOption.dataset[0].source.push(source);

    if (chartOption.dataset[0].source.length > maxDataCount) chartOption.dataset[0].source.shift();
    // 为图表设置选项
    chart.setOption(chartOption as echarts.EChartsOption);
  }
}


// 基础配置一下Echarts
async function initChart(chartDOM: HTMLElement, chartOption: DeviceDataChartOption, dimensionTag: string, area: boolean = false, valueRange: number[] | null = null) : Promise<echarts.EChartsType> {
  // 设置图表主题
  echarts.registerTheme('walden', walden)
  // 根据页面元素生成图表对象
  let chart = echarts.init(chartDOM, "walden");
  // 获取用于初次展示的数据
  let datapacks = await getData(deviceNumber, true).catch((err)=>{console.log(err)}) as  DataResponse.Datapack[];
  // 在数据包中查找特定维度的数据
  if (datapacks.length > 0) {
    let dimensionIndex = 0;
    let found = false;
    for (let i = 0; i < datapacks[0].data.length; i++) {
      if (datapacks[0].data[i].name == dimensionTag) {
        dimensionIndex = i;
        found = true;
        break;
      }
    }
    if (!found) {
      alert("未找到条目: " + dimensionTag);
      return chart;
    }
    // chartOption是用于设置图表的选项对象, 通过修改它可以使图表产生不同的显示效果
    // 图表标题设置为维度的名称
    chartOption.title.text = dimensionTag;
    // 根据维度命名坐标轴
    chartOption.dataset[0].dimensions = ["时间", dimensionTag];
    // 设置显示的数据维度
    chartOption.dataset[1].transform.config.dimension = dimensionTag;
    chartOption.series[0].encode = {
      x: "时间",
      y: dimensionTag
    };
    if (area) {
      chartOption.series[0].areaStyle.opacity = 0.2;
    }
    // 设置数据展示范围
    if (valueRange != null) {
      chartOption.yAxis.min = valueRange[0];
      chartOption.yAxis.max = valueRange[1];
    }
    // 设置坐标轴单位
    chartOption.yAxis.name = `值 / ${datapacks[0].data[dimensionIndex].unit}`
    // 为可视化数据集添加数据
    let sourceSet = [];
    for (let i = 0; i < datapacks.length; i++) {
      let source: Source = {};
      source["时间"] = new Date(datapacks[i].data[dimensionIndex].time).toLocaleString();
      source[dimensionTag] = datapacks[i].data[dimensionIndex].value;
      sourceSet.push(source);
    }
    chartOption.dataset[0].source = sourceSet.reverse();
  }
  // 为图表对象设置选项
  chart.setOption(chartOption as echarts.EChartsOption);
  // 返回图表对象
  return chart;
}

</script>
